package com.azh.server.tx;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Objects;

import com.azh.server.util.ExceptionUtils;
import com.azh.server.util.FileCommonUtils;

/**
 * @author zhaozhenhang <zhaozhenhang@kuaishou.com>
 * Created on 2022-04-24
 */
public interface TxManager {

    /**
     * 开启一个事物
     * @return
     */
    public long begin();

    /**
     * 提交一个事物
     * @param txId 事物id
     */
    public void commit(long txId);

    /**
     * 取消事物（回滚)
     * @param txId
     */
    public void abort(long txId);

    /**
     * 查询事物是否在进行的状态
     * @param txId
     * @return
     */
    public boolean isActive(long txId);

    /**
     * 查询一个事物是否已经提交
     * @param txId
     * @return
     */
    public boolean isCommitted(long txId);

    /**
     * 判断该事物是否已经取消
     * @param txId
     * @return
     */
    public boolean isAborted(long txId);

    /**
     * 关闭事物
     */
    public void close();

    public static TxManagerImpl create(String path) {
        File file = new File(path + TxManagerImpl.TX_ID_SUFFIX);
        try {
            if (!file.createNewFile()) {
                ExceptionUtils.getMessage(new FileNotFoundException());
            }
        } catch (Exception e) {
            ExceptionUtils.getMessage(e);
        }
        if (FileCommonUtils.canReadOrWrite(file)) {
            ExceptionUtils.getMessage(new Exception("文件无法读写，可能是因为没有权限或者其他原因..."));
        }
        FileChannel channel = null;
        RandomAccessFile refFile = null;
        try {
            refFile = new RandomAccessFile(file, "rw");
            channel = refFile.getChannel();
        } catch (FileNotFoundException e) {
            ExceptionUtils.getMessage(e);
        }
        // 写tx_id文件头, 将文件写null
        ByteBuffer buffer = ByteBuffer.wrap(new byte[TxManagerImpl.TX_ID_HEADER_LENGTH]);
        try {
            Objects.requireNonNull(channel).position(0);
            channel.write(buffer);
        } catch (IOException e) {
            ExceptionUtils.getMessage(e);
        }
        return new TxManagerImpl(refFile, channel);
    }

    public static TxManagerImpl open(String path) {
        File file = new File(path + TxManagerImpl.TX_ID_SUFFIX);
        if (!file.exists()) {
            ExceptionUtils.getMessage(new FileNotFoundException("对应的tx文件不存在"));
        }
        if (FileCommonUtils.canReadOrWrite(file)) {
            ExceptionUtils.getMessage(new Exception("文件无法读写，可能是因为没有权限或者其他原因..."));
        }
        FileChannel channel = null;
        RandomAccessFile refFile = null;
        try {
            refFile = new RandomAccessFile(file, "rw");
            channel = refFile.getChannel();
        } catch (FileNotFoundException e) {
            ExceptionUtils.getMessage(e);
        }
        return new TxManagerImpl(refFile, channel);
    }
}
